package com.demo.statemachine.redis;

import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.statemachine.config.EnableStateMachineFactory;
import org.springframework.statemachine.config.StateMachineConfigurerAdapter;
import org.springframework.statemachine.config.StateMachineFactory;
import org.springframework.statemachine.config.builders.StateMachineConfigurationConfigurer;
import org.springframework.statemachine.config.builders.StateMachineStateConfigurer;
import org.springframework.statemachine.config.builders.StateMachineTransitionConfigurer;
import org.springframework.statemachine.data.redis.RedisPersistingStateMachineInterceptor;
import org.springframework.statemachine.data.redis.RedisStateMachineRepository;
import org.springframework.statemachine.persist.StateMachineRuntimePersister;
import org.springframework.statemachine.service.DefaultStateMachineService;
import org.springframework.statemachine.service.StateMachineService;

import java.util.EnumSet;
@EnableStateMachineFactory
@Configuration
public class StateMachineConfig extends StateMachineConfigurerAdapter<States, Events> {

    @Autowired
    private StateMachineRuntimePersister<States, Events, String> stateMachineRuntimePersister;

    @Bean
    public StateMachineRuntimePersister<States, Events, String> stateMachineRuntimePersister(RedisStateMachineRepository redisStateMachineRepository) {
        return new RedisPersistingStateMachineInterceptor<States, Events, String>(redisStateMachineRepository);
    }

    @Override
    public void configure(StateMachineConfigurationConfigurer<States, Events> config) throws Exception {
        config.withPersistence().runtimePersister(stateMachineRuntimePersister);
    }

    @Override
    public void configure(StateMachineStateConfigurer<States, Events> states) throws Exception {
        states.withStates().initial(States.S1).states(EnumSet.allOf(States.class));
    }

    @Override
    public void configure(StateMachineTransitionConfigurer<States, Events> transitions) throws Exception {
        transitions
                .withExternal()
                .source(States.S1).target(States.S2)
                .event(Events.E1)
                .and()
                .withExternal()
                .source(States.S2).target(States.S3)
                .event(Events.E2)
                .and()
                .withExternal()
                .source(States.S3).target(States.S4)
                .event(Events.E3)
                .and()
                .withExternal()
                .source(States.S4).target(States.S5)
                .event(Events.E4)
                .and()
                .withExternal()
                .source(States.S5).target(States.S6)
                .event(Events.E5)
                .and()
                .withExternal()
                .source(States.S6).target(States.S1)
                .event(Events.E6);

    }

    @Bean
    public StateMachineService<States, Events> statesEventsStateMachineService(
            StateMachineFactory<States, Events> sateMachineFactory,
            StateMachineRuntimePersister<States, Events, String> stateMachineRuntimePersister) {
        return new DefaultStateMachineService<>(sateMachineFactory, stateMachineRuntimePersister);
    }


}
